package by.dvrudenko.avtobaza.services.impl;

import java.util.List;
import java.util.Random;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.metamodel.SingularAttribute;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import by.dvrudenko.avtobaza.dataaccess.RouteDao;
import by.dvrudenko.avtobaza.dataaccess.UserDao;
import by.dvrudenko.avtobaza.dataaccess.UserOrderDao;
import by.dvrudenko.avtobaza.datamodel.Car_;
import by.dvrudenko.avtobaza.datamodel.Driver;
import by.dvrudenko.avtobaza.datamodel.Route;
import by.dvrudenko.avtobaza.datamodel.User;
import by.dvrudenko.avtobaza.datamodel.enums.OrderStatus;
import by.dvrudenko.avtobaza.datamodel.enums.UserRole;
import by.dvrudenko.avtobaza.services.CarService;
import by.dvrudenko.avtobaza.services.DriverService;
import by.dvrudenko.avtobaza.services.RouteService;
import by.dvrudenko.avtobaza.services.UserOrderService;
import by.dvrudenko.avtobaza.services.UserService;

@Service
public class RouteServiceImpl implements RouteService {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(RouteServiceImpl.class);

	@Inject
	private RouteDao daoRoute;

	@Inject
	private UserOrderDao daoUserOrder;

	@Inject
	private UserDao daoUser;
	
	@Inject
	private UserService serviceUser;	
	
	@Inject
	private DriverService serviceDriver;

	@Inject
	private CarService serviceCar;

	@Inject
	private UserOrderService serviceUserOrder;

	@PostConstruct
	private void init() {
		LOGGER.info("Instance of RouteService is created. Class is: {}",
				getClass().getName());
	}

	@Override
	public Route get(Long id) {
		Route entity = daoRoute.getById(id);
		return entity;
	}

	@Override
	public void saveOrUpdate(Route route) {
		if (route.getId() == null) {
			LOGGER.debug("Save new: {route}", route);
			// при создании нового маршрута, OrderStatus ставится в стотояние
			// rides_for_cargo
			route.getUserOrder().setOrderStatus(OrderStatus.rides_for_cargo);
			daoUserOrder.update(route.getUserOrder());
			daoRoute.insert(route);
		} else {
			LOGGER.debug("Update: {route}", route);
			daoRoute.update(route);
		}
	}

	@Override
	public void delete(Route route) {
		LOGGER.debug("Remove: {route}", route);
		daoRoute.delete(route.getId());

	}

	@Override
	public void deleteAll() {
		LOGGER.debug("Remove all route");
		daoRoute.deleteAll();
	}

	@Override
	public List<Route> getAllRouteActive(Boolean active) {
		return daoRoute.getAllRouteActive(active);
	}

	@Override
	public List<Route> getAllRoute() {
		return daoRoute.getAllRoute();
	}

	@Override
	public List<Route> getAllActiveRouteByStatus(OrderStatus orderStatus) {
		return daoRoute.getAllActiveRouteByStatus(orderStatus);
	}

	@Override
	// меняет остояние маршрута на finish состояние водителя и машины на
	// свободен.
	public void changeRouteStatusByOrderId(Long id) {
		Route route = getSingleRouteById(id);
		route.setActive(false);
		saveOrUpdate(route);
		serviceDriver.changeDriverWorkStatus(route.getDriver().getId(), false);
		serviceCar.changeBooleanValue(Car_.work, route.getCar().getId(), false);
		serviceUserOrder.changeOrderStatus(route.getUserOrder().getId(),
				OrderStatus.finish);
	}

	@Override
	public Route getSingleRouteById(Long id) {
		return daoRoute.getSingleRouteByUserOrderId(id);
	}

	@Override
	public Integer getAcomplishRoutesByDriverId(Long id) {
		return daoRoute.getAcomplishRoutesByDriverId(id);
	}

	@Override
	// возвращает случайный активный маршрут
	// если их нет, возвращает любой маршрут
	public Route getRandomActiveRoute() {
		List<Route> listRoute = daoRoute.getAllRouteActive(true);
		if (listRoute.size() == 0) {
			listRoute = daoRoute.getAllRouteActive(false);
		}
		Integer numberRoute = listRoute.size();
		Random rand = new Random();
		int randomNum = rand.nextInt(numberRoute);
		return listRoute.get(randomNum);
	}

	@Override
	public List<Route> getAllRoute(SingularAttribute<Route, ?> attr,
			boolean ascending, int startRecord, int pageSize,  Long DriverId) {
		return daoRoute.getAllDriver(attr, ascending, startRecord, pageSize, DriverId);
	}

	
	@Override // возвращает к-во записей , для DRIVER или ADMIN
	public Long getCount(Long id) {
		Long count;
		User user = serviceUser.get(id);
		if (user.getRole().equals(UserRole.DRIVER)){
			// определяем водителя по переданному id
			Driver driver = serviceDriver.getDriverByUserId(id);			
			count = daoRoute.getCount(driver.getId());
		}else if (user.getRole().equals(UserRole.ADMIN)){
			// возвращает весь список 
			count = daoRoute.getCount(null);
		}else {
			throw new IllegalArgumentException("illegal user role, must be equals DRIVER or ADMIN");
		}
		return count;
	}

	@Override
	public Route getRouteByUserOrder(Long id) {
		return daoRoute.getRouteByUserOrder(id);
	}

	@Override
	public void sendDriverToRoute(Route route) {
		serviceDriver.changeDriverWorkStatus(route.getDriver().getId(), true);
		serviceCar.changeBooleanValue(Car_.work, route.getCar().getId(), true);
		route.getUserOrder().setOrderStatus(OrderStatus.rides_for_cargo);
		serviceUserOrder.saveOrUpdate(route.getUserOrder());
		saveOrUpdate(route);		
	}

}
